(function (w) {
  class HD {
    constructor(executor) {
      this.data = null;
      this.status = 'pending';
      this.callBacks = [];
      try {
        executor(this.resolve.bind(this), this.reject.bind(this))
      } catch (e) {
        this.reject(e)
      }
    }
    resolve(value) {
      if (this.status !== 'pending') {
        return
      }
      this.status = 'success';
      this.data = value;
      if (this.callBacks.length) {
        setTimeout(() => {
          this.callBacks.forEach(v => {
            v.onResolved()
          })
        })
      }
    }
    reject(reason) {
      if (this.status !== 'pending') {
        return
      }
      this.status = 'fail';
      this.data = reason
      if (this.callBacks.length) {
        setTimeout(() => {
          this.callBacks.forEach(v => {
            v.onRejected()
          })
        })
      }
    }
    then(onResolved, onRejected) {
      const self = this;
      onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
      onResolved = typeof onResolved === 'function' ? onResolved : value => value;
      return new HD((resolve, reject) => {
        function handle(fn) {
          try {
            const result = fn(self.data);
            if (result instanceof HD) {
              result.then(resolve, reject)
            } else {
              resolve(result)
            }

          } catch (e) {
            reject(e)
          }
        }



        if (self.status === 'success') {
          handle(onResolved)
        } else if (self.status === 'fail') {
          handle(onRejected)
        } else {
          self.callBacks.push({
            onRejected: function () { handle(onRejected) },
            onResolved: function () {
              handle(onResolved)
            }
          })
        }
      })
    }
    catch(onRejected) {
      return this.then(null, onRejected)
    }
  }
  w.HD = HD
})(window)